package com.btm.easymetadata.server.service;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.btm.easymetadata.server.entity.dao.DataField;
import com.btm.easymetadata.server.entity.dao.LinkField;
import com.btm.easymetadata.server.entity.dao.ProductRequirementDocument;
import com.btm.easymetadata.server.entity.dto.DataFieldDTO;
import com.btm.easymetadata.server.entity.dto.LinkDTO;
import com.btm.easymetadata.server.entity.vo.DataFieldVO;
import com.btm.easymetadata.server.entity.vo.PrdVO;
import com.btm.easymetadata.server.mapper.mybatisplus.DataFieldMapper;
import com.btm.easymetadata.server.mapper.mybatisplus.LinkFieldMapper;
import com.btm.easymetadata.server.util.DAOtoVOUtil;
import com.btm.easymetadata.server.util.DTOtoDAOUtil;
import lombok.AllArgsConstructor;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;
import org.springframework.util.StringUtils;

import java.util.Collections;
import java.util.List;
import java.util.Objects;
import java.util.stream.Collectors;

@Service
@AllArgsConstructor
public class DataFieldService {

    private final DataFieldMapper dataFieldMapper;
    private final LinkFieldMapper linkFieldMapper;
    private final LinkService linkService;

    @Transactional(rollbackFor = Exception.class)
    public boolean add(DataFieldDTO dataFieldDTO) {
        LambdaQueryWrapper<DataField> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(StringUtils.hasText(dataFieldDTO.getDatabaseName()),DataField::getDatabaseName, dataFieldDTO.getDatabaseName())
                .eq(StringUtils.hasText(dataFieldDTO.getDatabaseType()),DataField::getDatabaseType, dataFieldDTO.getDatabaseType())
                .eq(StringUtils.hasText(dataFieldDTO.getTableName()),DataField::getTableName, dataFieldDTO.getTableName())
                .eq(StringUtils.hasText(dataFieldDTO.getFieldName()),DataField::getFieldName, dataFieldDTO.getFieldName());
        List<DataField> dataFields = dataFieldMapper.selectList(wrapper);
        if (CollectionUtils.isEmpty(dataFields)) {
            DataField dataField = DTOtoDAOUtil.INSTANCE.getDataFieldFromDTO(dataFieldDTO);
            if (1 == dataFieldMapper.insert(dataField)) {
                if (Objects.nonNull(dataFieldDTO.getPrdInfoId())) {
                    LinkDTO linkDTO = new LinkDTO();
                    linkDTO.setPrdInfoId(dataFieldDTO.getPrdInfoId());
                    linkDTO.setDataFieldId(dataField.getId());
                    linkService.linkTo(linkDTO);
                }
                if (Objects.nonNull(dataFieldDTO.getLinkFieldId()) && Objects.nonNull(dataFieldDTO.getLinkType())) {
                    LinkField linkField = new LinkField();
                    linkField.setFieldFrom("from".equals(dataFieldDTO.getLinkType()) ? dataField.getId() : dataFieldDTO.getLinkFieldId());
                    linkField.setFieldTo("to".equals(dataFieldDTO.getLinkType()) ? dataField.getId() : dataFieldDTO.getLinkFieldId());
                    linkFieldMapper.insert(linkField);
                }
                return true;
            }
        }
        // 已经存在的直接返回false
        return false;
    }

    public boolean update(DataFieldDTO dataFieldDTO) {
        if (Objects.isNull(dataFieldDTO.getId())) {
            return false;
        }
        return 1 == dataFieldMapper.updateById(DTOtoDAOUtil.INSTANCE.getDataFieldFromDTO(dataFieldDTO));
    }

    public IPage<DataFieldVO> list(DataFieldDTO dataFieldDTO) {
        LambdaQueryWrapper<DataField> wrapper = new LambdaQueryWrapper<>();
        wrapper.like(StringUtils.hasText(dataFieldDTO.getFieldName()), DataField::getFieldName, dataFieldDTO.getFieldName())
                .like(StringUtils.hasText(dataFieldDTO.getFieldDesc()), DataField::getFieldDesc, dataFieldDTO.getFieldDesc())
                .like(StringUtils.hasText(dataFieldDTO.getTableName()), DataField::getTableName, dataFieldDTO.getTableName())
                .like(StringUtils.hasText(dataFieldDTO.getDatabaseName()), DataField::getDatabaseName, dataFieldDTO.getDatabaseName());
        if (Objects.nonNull(dataFieldDTO.getPrdInfoId())) {
            if (dataFieldDTO.getLinkPrd()) {
                wrapper.exists("select 1 from link_field_prd_info l where l.field_id = data_field.id and l.prd_info_id = " + dataFieldDTO.getPrdInfoId());
            } else {
                wrapper.notExists("select 1 from link_field_prd_info l where l.field_id = data_field.id and l.prd_info_id = " + dataFieldDTO.getPrdInfoId());
            }
        }
        if (Objects.nonNull(dataFieldDTO.getLinkFieldId()) && Objects.nonNull(dataFieldDTO.getLinkType())) {
            if ("from".equals(dataFieldDTO.getLinkType())) {
                wrapper.exists("select 1 from link_field l where l.field_from = " + dataFieldDTO.getLinkFieldId() + " and l.field_to = data_field.id");
            } else {
                wrapper.exists("select 1 from link_field l where l.field_to = " + dataFieldDTO.getLinkFieldId() + " and l.field_from = data_field.id");
            }
        }
        IPage<DataField> pages = new Page<>(dataFieldDTO.getPageNumber(), dataFieldDTO.getPageSize());
        IPage<DataField> pageResult = dataFieldMapper.selectPage(pages, wrapper);
        IPage<DataFieldVO> result = new Page<>();
        result.setCurrent(pageResult.getCurrent());
        result.setPages(pageResult.getPages());
        result.setSize(pageResult.getSize());
        result.setTotal(pageResult.getTotal());
        List<DataField> records = pageResult.getRecords();
        if (!CollectionUtils.isEmpty(records)) {
            result.setRecords(records.stream().map(DAOtoVOUtil.INSTANCE::getDataFieldFromDTO).collect(Collectors.toList()));
        } else {
            result.setRecords(Collections.emptyList());
        }
        return result;
    }

}
